import json
import urllib.parse
from config import *
import os
import uuid
from LRU_cache import LRUCache
import pickle
import asyncio
import json
#普通聊天信息
all_user_dict = LRUCache(USER_SAVE_MAX)
#创建赛事
all_user_game_dict = {}

all_filed_dict = json.loads("{\"address\":{\"name\":\"赛事地点\",\"format\":\"string\",\"describe\":\"赛事举办的详细地址,如:北京市海淀区北太平庄路18号\",\"content\":\"\"},"
                        "\"siteAddress\":{\"name\":\"场馆名称\",\"format\":\"string\",\"describe\":\"赛事举办的场馆名称,如:北京体育大学体育馆\",\"content\":\"\"},"
                        "\"sites\":{\"name\":\"比赛场地\",\"format\":\"string\",\"describe\":\"赛事的具体比赛场地,如:A区网球场,B区羽毛球馆\",\"content\":\"\"},"
                        "\"startTime\":{\"name\":\"比赛开始时间\",\"format\":\"string(date-time)\",\"describe\":\"赛事开始的具体日期和时间,格式为yyyy-MM-dd HH:mm:ss。如果用户使用相对时间表达,如'明天'、'下周二'等,请根据当前日期进行转换。\",\"content\":\"\"},"
                        "\"endTime\":{\"name\":\"比赛结束时间\",\"format\":\"string(date-time)\",\"describe\":\"赛事结束的具体日期和时间,格式为yyyy-MM-dd HH:mm:ss。如果用户使用相对时间表达,如'后天'、'下周五'等,请根据当前日期进行转换。\",\"content\":\"\"},"
                        "\"deadline\":{\"name\":\"报名截止时间\",\"format\":\"string(date-time)\",\"describe\":\"赛事报名截止的具体日期和时间,格式为yyyy-MM-dd HH:mm:ss。如果用户使用相对时间表达,如'今晚'、'下周一中午'等,请根据当前日期进行转换。\",\"content\":\"\"},"
                        "\"organizerList\":[{\"name\":\"主办方\",\"format\":\"string\",\"describe\":\"赛事的主办单位名称,如:中国网球协会,北京体育局\",\"content\":\"\"}]}")
async def save_all_user_dict():
    """
    异步存储all_user_dict
    :return:
    """
    await asyncio.sleep(0)
    lock.acquire()
    with open(os.path.join(DATA_DIR, USER_DICT_FILE), "wb") as f:
        pickle.dump(all_user_dict, f)
    logger.debug("聊天j存储成功")
    lock.release()


def get_user_info(user_id):
    """
    获取用户信息
    :param user_id: 用户id
    :return: 用户信息
    """
    lock.acquire()
    user_info = all_user_dict.get(user_id)
    lock.release()
    return user_info


def backup_user_dict_file():
    """
    备份用户字典文件
    :return:
    """
    backup_file_name = USER_DICT_FILE.replace(".pkl",
                                              f"_buckup_{datetime.datetime.now().strftime('%Y%m%d%H%M%S%f')}.pkl")
    shutil.copy(os.path.join(DATA_DIR, USER_DICT_FILE), os.path.join(DATA_DIR, backup_file_name))
    logger.warning(f"备份用户字典文件{USER_DICT_FILE}为{backup_file_name}")


def auth(request_head, session):
    """
    验证用户身份
    :param request_head: 请求头
    :param session: session
    :return: 验证结果
    """
    user_id = request_head.get("user-id")
    user_id = urllib.parse.unquote(user_id)
    password = request_head.get("password")
    apikey = request_head.get("api-key")

    user_info = get_user_info(user_id)
    if len(PASSWORD) > 0 and password != PASSWORD:
        return False, "访问密码错误，请在设置中填写正确的访问密码"

    if user_info is not None:
        session['user_id'] = user_id
        if apikey is not None and len(apikey) > 1 and apikey != "null" and apikey != "undefined":
            user_info['apikey'] = apikey
        else:
            user_info['apikey'] = None
        return True, "success"
    else:
        if session.get('user_id') is not None:
            del session['user_id']
        return False, "用户不存在，请在设置中填写正确的用户id，或发送new:xxx创建新的用户，其中xxx为你的自定义id"


def new_chat_dict(user_id, name, send_time):
    return {
        "chat_with_history": False,
        "have_chat_context": 0,  # 从每次重置聊天模式后开始重置一次之后累计
        "name": name,
        "messages_history": [
            {"role": "assistant", "content": project_info},
            {"role": "web-system", "content": f"当前对话的用户id为{user_id}"},
            {"role": "web-system", "content": send_time},
            {"role": "web-system", "content": f"你已添加了{name}，现在可以开始聊天了。"},
        ]
    }


def new_user_dict(user_id, send_time):
    chat_id = str(uuid.uuid1())
    user_dict = {"chats": {chat_id: new_chat_dict(user_id, "默认对话", send_time)},
                 "selected_chat_id": chat_id,
                 "default_chat_id": chat_id}

    user_dict['chats'][chat_id]['messages_history'].insert(1, {"role": "assistant",
                                                               "content": "创建新的用户id成功，请牢记该id"})
    return user_dict


def get_message_context(message_history, have_chat_context, chat_with_history):
    """
    获取上下文
    :param message_history:
    :param have_chat_context:
    :param chat_with_history:
    :return:
    """
    message_context = []
    total = 0
    if chat_with_history:
        num = min([len(message_history), CHAT_CONTEXT_NUMBER_MAX, have_chat_context])
        # 获取所有有效聊天记录
        valid_start = 0
        valid_num = 0
        for i in range(len(message_history) - 1, -1, -1):
            message = message_history[i]
            if message['role'] in {'assistant', 'user'}:
                valid_start = i
                valid_num += 1
            if valid_num >= num:
                break

        for i in range(valid_start, len(message_history)):
            message = message_history[i]
            if message['role'] in {'assistant', 'user'}:
                message_context.append(message)
                total += len(message['content'])
    else:
        message_context.append(message_history[-1])
        total += len(message_history[-1]['content'])

    logger.info(f"len(message_context): {len(message_context)} total: {total}")
    return message_context


def check_user_bind(current_session):
    """
    检查用户是否绑定，如果没有绑定则重定向到index
    :param current_session: 当前session
    :return: 当前session
    """
    if current_session.get('user_id') is None:
        return False
    return True


def check_load_pickle():
    global all_user_dict

    data_files = os.listdir(DATA_DIR)
    have_move = False  # 匹配新版迁移，新版本的用户记录移到了data目录中
    for file in data_files:
        if re.match(r"all_user_dict_.*\.pkl", file):
            have_move = True
            break

    if not have_move:
        files = os.listdir()
        for file in files:
            if re.match(r"all_user_dict_.*\.pkl", file):
                shutil.move(file, DATA_DIR)

    if os.path.exists(os.path.join(DATA_DIR, USER_DICT_FILE)):
        with open(os.path.join(DATA_DIR, USER_DICT_FILE), "rb") as pickle_file:
            all_user_dict = pickle.load(pickle_file)
            all_user_dict.change_capacity(USER_SAVE_MAX)
        logger.warning(f"已加载上次存储的用户上下文，共有{len(all_user_dict)}用户, 分别是")
        for i, user_id in enumerate(list(all_user_dict.keys())):
            info = f"{i} 用户id:{user_id}\t对话统计:\t"
            user_info = all_user_dict.get(user_id)
            for chat_id in user_info['chats'].keys():
                info += f"{user_info['chats'][chat_id]['name']}[{len(user_info['chats'][chat_id]['messages_history'])}] "
            logger.info(info)
    elif os.path.exists(os.path.join(DATA_DIR, "all_user_dict_v2.pkl")):  # 适配V2
        logger.warning('检测到v2版本的上下文，将转换为v3版本')
        with open(os.path.join(DATA_DIR, "all_user_dict_v2.pkl"), "rb") as pickle_file:
            all_user_dict = pickle.load(pickle_file)
            all_user_dict.change_capacity(USER_SAVE_MAX)
        logger.warning(f"共有用户个{len(all_user_dict)}")
        for user_id in list(all_user_dict.keys()):
            user_info: dict = all_user_dict.get(user_id)
            for chat_id in user_info['chats'].keys():
                if "messages_history" in user_info['chats'][chat_id]:
                    for i in range(len(user_info['chats'][chat_id]['messages_history'])):
                        # 将system关键字改为 web-system
                        if "role" in user_info['chats'][chat_id]['messages_history'][i] and \
                                user_info['chats'][chat_id]['messages_history'][i]["role"] == "system":
                            user_info['chats'][chat_id]['messages_history'][i]["role"] = "web-system"

        asyncio_run(save_all_user_dict())

    elif os.path.exists(os.path.join(DATA_DIR, "all_user_dict.pkl")):  # 适配V1版本
        logger.warning('检测到v1版本的上下文，将转换为v3版本')
        with open(os.path.join(DATA_DIR, "all_user_dict.pkl"), "rb") as pickle_file:
            all_user_dict = pickle.load(pickle_file)
            all_user_dict.change_capacity(USER_SAVE_MAX)
        logger.warning(f"共有用户{len(all_user_dict)}个")
        for user_id in list(all_user_dict.keys()):
            user_info: dict = all_user_dict.get(user_id)
            if "messages_history" in user_info:
                user_dict = new_user_dict(user_id, "")
                chat_id = user_dict['selected_chat_id']
                user_dict['chats'][chat_id]['messages_history'] = user_info['messages_history']
                user_dict['chats'][chat_id]['chat_with_history'] = user_info['chat_with_history']
                user_dict['chats'][chat_id]['have_chat_context'] = user_info['have_chat_context']
                all_user_dict.put(user_id, user_dict)  # 更新
        asyncio_run(save_all_user_dict())
    else:
        with open(os.path.join(DATA_DIR, USER_DICT_FILE), "wb") as pickle_file:
            pickle.dump(all_user_dict, pickle_file)
        logger.warning("未检测到上次存储的用户上下文，已创建新的用户上下文")

    # 判断all_user_dict是否为None且时LRUCache的对象
    if all_user_dict is None or not isinstance(all_user_dict, LRUCache):
        logger.warning("all_user_dict为空或不是LRUCache对象，已创建新的LRUCache对象")
        all_user_dict = LRUCache(USER_SAVE_MAX)



